﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace SGD_ParticleEditor
{
    class Emitter
    {
        string name;
        float lifetime, lifetimeVariation;
        float positionX, positionY;
        float minVelocityX, maxVelocityX;
        float minVelocityY, maxVelocityY; 
        float startScale, startScaleVariation;
        float endScale, endScaleVariation;
        float delayTime;
        float startTime;         // Helper variable for delay time
        float width, widthOffset;
        float height, heightOffset;
        float accelerationX, accelerationY;
        int imageWidth, imageHeight;        // Helper variables for draw offset
        int imageID;
        int numParticles;
        bool isEmitting;
        bool isContinousPlay;    // true if continous play, false if 1 shot
        Color startColor;
        Color endColor;
        List<Particle> particleList;
        Random random;

        public float MaxVelocityX
        {
            get { return maxVelocityX; }
            set { maxVelocityX = value; }
        }

        public float MinVelocityX
        {
            get { return minVelocityX; }
            set { minVelocityX = value; }
        }

        public float MaxVelocityY
        {
            get { return maxVelocityY; }
            set { maxVelocityY = value; }
        }

        public float MinVelocityY
        {
            get { return minVelocityY; }
            set { minVelocityY = value; }
        }

        public float AccelerationX
        {
            get { return accelerationX; }
            set { accelerationX = value; }
        }

        public float AccelerationY
        {
            get { return accelerationY; }
            set { accelerationY = value; }
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public float LifeTime
        {
            get { return lifetime; }
            set { lifetime = value; }
        }

        public float LifetimeVariation
        {
            get { return lifetimeVariation; }
            set { lifetimeVariation = value; }
        }

        public float PositionX
        {
            get { return positionX; }
            set { positionX = value; }
        }

        public float PositionY
        {
            get { return positionY; }
            set { positionY = value; }
        }

        public float StartScale
        {
            get { return startScale; }
            set { startScale = value; }
        }

        public float StartScaleVariation
        {
            get { return startScaleVariation; }
            set { startScaleVariation = value; }
        }

        public float EndScale
        {
            get { return endScale; }
            set { endScale = value; }
        }

        public float EndScaleVariation
        {
            get { return endScaleVariation; }
            set { endScaleVariation = value; }
        }

        public int ImageID
        {
            get { return imageID; }
            set { imageID = value; }
        }

        public int ImageWidth
        {
            get { return imageWidth; }
            set { imageWidth = value; }
        }

        public int ImageHeight
        {
            get { return imageHeight; }
            set { imageHeight = value; }
        }

        public int NumParticles
        {
            get { return numParticles; }
            set { numParticles = value; }
        }

        public float DelayTime
        {
            get { return delayTime; }
            set { delayTime = value; }
        }

        public float Width
        {
            get { return width; }
            set { width = value; }
        }

        public float Height
        {
            get { return height; }
            set { height = value; }
        }

        public float WidthOffset
        {
            get { return widthOffset; }
            set { widthOffset = value; }
        }

        public float HeightOffset
        {
            get { return heightOffset; }
            set { heightOffset = value; }
        }

        public bool IsEmitting
        {
            get { return isEmitting; }
            set { isEmitting = value; }
        }

        public bool IsContinousPlay
        {
            get { return isContinousPlay; }
            set { isContinousPlay = value; }
        }

        public Color StartColor
        {
            get { return startColor; }
            set { startColor = value; }
        }

        public Color EndColor
        {
            get { return endColor; }
            set { endColor = value; }
        }

        internal List<Particle> ParticleList
        {
            get { return particleList; }
            set { particleList = value; }
        }

        public Emitter(int _imageID, int _imageWidth, int _imageHeight)
        {
            // Name
            name = "Default";

            // Life
            lifetime = 2.0f;
            lifetimeVariation = 1.0f;

            // Position
            positionX = 312.0f;
            positionY = 284.0f;

            // Dimensions
            width = 0.0f;
            height = 0.0f;
            widthOffset = width / 2;
            heightOffset = height / 2;

            // Movement
            minVelocityX = -100.0f;
            maxVelocityX = 100.0f;
            minVelocityY = -100.0f;
            maxVelocityY = 100.0f;
            accelerationX = 0.0f;
            accelerationY = 0.0f;
            
            // Size
            startScale = 1.0f;
            startScaleVariation = 0.0f;
            endScale = 0.1f;
            endScaleVariation = 0.0f;

            // Colors
            startColor = Color.Firebrick;
            endColor = Color.WhiteSmoke;

            // Others
            isContinousPlay = true;
            isEmitting = true;
            delayTime = 3.0f;
            startTime = 0.0f;
            numParticles = 500;
            imageID = _imageID;
            imageWidth = _imageWidth;
            imageHeight = _imageHeight;
            particleList = new List<Particle>();
            random = new Random();
        }

        private float RandomValue(float _minValue, float _maxValue)
        {
            return (float)random.NextDouble() * (_maxValue - _minValue) + _minValue;
        }

        public void CreateParticle()
        {
            // Set particle with random values
            Particle tempParticle = new Particle(
                            RandomValue(lifetime - lifetimeVariation, lifetime + lifetimeVariation),
                            RandomValue(startScale - startScaleVariation, startScale + startScaleVariation),
                            RandomValue(endScale - endScaleVariation, endScale + endScaleVariation),
                            RandomValue(positionX - widthOffset, positionX + widthOffset),
                            RandomValue(positionY - heightOffset, positionY + heightOffset),
                            startColor, endColor,
                            RandomValue(minVelocityX, maxVelocityX),
                            RandomValue(minVelocityY, maxVelocityY),
                            accelerationX, accelerationY);

            // Add to the list
            particleList.Add(tempParticle);
        }

        public void Update(float _dt)
        {
            // Add new particles if needed
            if (particleList.Count < numParticles && isEmitting)
                CreateParticle();
            else if (!isContinousPlay)
                isEmitting = false;

            if (!isEmitting)
            {
                startTime += _dt;
                if (startTime >= delayTime && particleList.Count == 0)
                {
                    startTime = 0.0f;
                    isEmitting = true;
                }
            }

            // Destroy any particles past their lifetime
            for (int i = 0; i < particleList.Count; ++i)
            {
                particleList[i].Update(_dt);

                if (particleList[i].CurrLife <= 0.0f)
                    particleList.RemoveAt(i);
            }
        }

        public void Render()
        {
            for (int i = 0; i < particleList.Count; ++i)
            {
                if (imageID == -1)
                    break;
                SGD.ManagedTextureManager.Instance.Draw(imageID, (int)particleList[i].PositionX - imageWidth, (int)particleList[i].PositionY - imageHeight,
                    particleList[i].CurrScale, particleList[i].CurrScale, Rectangle.Empty, 0, 0, 0, particleList[i].CurrColor.ToArgb());
            }
        }
    }
}
